home *** CD-ROM | disk | FTP | other *** search
/ Aminet 24 / Aminet 24 (1998)(GTI - Schatztruhe)[!][Apr 1998].iso / Aminet / dev / c / vbcc.lha / vbcc / pasm / eval.c < prev    next >
C/C++ Source or Header  |  1998-02-17  |  21KB  |  807 lines

  1. /* $VER: pasm eval.c V0.7 (01.01.98)
  2.  *
  3.  * This file is part of pasm, a portable PowerPC assembler.
  4.  * Copyright (c) 1997-98  Frank Wille
  5.  *
  6.  * pasm is freeware and part of the portable and retargetable ANSI C
  7.  * compiler vbcc, copyright (c) 1995-98 by Volker Barthelmann.
  8.  * pasm may be freely redistributed as long as no modifications are
  9.  * made and nothing is charged for it. Non-commercial usage is allowed
  10.  * without any restrictions.
  11.  * EVERY PRODUCT OR PROGRAM DERIVED DIRECTLY FROM MY SOURCE MAY NOT BE
  12.  * SOLD COMMERCIALLY WITHOUT PERMISSION FROM THE AUTHOR.
  13.  *
  14.  *
  15.  * v0.7 (01.01.98) phx
  16.  *      @ha, @h, @l are only allowed at the end of an operand, according
  17.  *      to GNU-as notation. '@' is only allowed as the first character in
  18.  *      a symbol (for @function and @object, for example).
  19.  *      Don't waste memory in makereloc() and makexref() by adding new
  20.  *      nodes to the current section if another pass is required
  21.  *      anyway.
  22.  * v0.5 (11.10.97) phx
  23.  *      getarg() works with \' and \" now.
  24.  * v0.4 (05.07.97) phx
  25.  *      R_PPC_TOC16 and R_PPC_REL14 support in makereloc() and makexref().
  26.  *      "(<term>)@l/h/ha" was not recognized.
  27.  *      A comment introducer '#' was erroneously treated as a macro
  28.  *      parameter in read_macro_params().
  29.  *      Undefined symbols are only automatically declared as externally
  30.  *      defined, if the -x option was given. Otherwise display an
  31.  *      error message.
  32.  *      Implementing backwards-evaluation of an expression in v0.3 was not
  33.  *      very smart (e.g. 4-1+2 => 1(!)) - changed to forward again... ;)
  34.  * v0.3 (20.04.97) phx
  35.  *      Bug in eval_expression() fixed, which sometimes caused the loss
  36.  *      of the last argument of an expression.
  37.  * v0.2 (25.03.97) phx
  38.  *      Writes ELF object for 32-bit PowerPC big-endian. Either absolute
  39.  *      or ELF output format may be selected. ELF is default for all
  40.  *      currently supported platforms. PPCasm supports nine different
  41.  *      relocation types (there are much more...).
  42.  *      Compiles and works also under NetBSD/amiga (68k).
  43.  *      Changed function declaration to 'new style' in all sources
  44.  *      (to avoid problems with '...' for example).
  45.  *      makexref() and makereloc() used wrong offset.
  46.  * v0.1 (11.03.97) phx
  47.  *      First test version with all PowerPC instructions and most
  48.  *      important directives. Only raw, absolute output.
  49.  * v0.0 (21.02.97) phx
  50.  *      File created.
  51.  */
  52.  
  53.  
  54. #define EVAL_C
  55. #include "ppcasm.h"
  56.  
  57.  
  58. char *getsymbol(struct GlobalVars *,char *);
  59. char *getarg(struct GlobalVars *,char *);
  60. char *skipspaces(char *);
  61. char *remquotes(char *);
  62. void checkEOL(char *);
  63. char *skipexpression(struct GlobalVars *,char *);
  64. void read_macro_params(struct GlobalVars *,struct ParsedLine *,
  65.                        struct MacroParams *,char *);
  66. char *getexp(struct GlobalVars *,char *,uint32 *,uint8);
  67. uint32 makereloc(struct GlobalVars *,struct Expression *);
  68. uint32 makexref(struct GlobalVars *,struct Expression *,uint8);
  69. char *getintexp(struct GlobalVars *,char *,uint32 *);
  70. char *eval_expression(struct GlobalVars *,struct Expression *,char *);
  71.  
  72. static uint32 hihalf(struct GlobalVars *,uint32);
  73. static uint32 lohalf(struct GlobalVars *,uint32);
  74. static uint32 read_hex(char *);
  75. static uint32 read_dec(char *);
  76. static uint32 read_oct(char *);
  77. static uint32 read_bin(char *);
  78. static uint32 read_str(char *);
  79.  
  80.  
  81.  
  82. /* table of valid symbol characters, 
  83.    0=invalid, 1=valid in whole symbol, 2=valid, but not as first char */
  84. static uint8 valid_symchars[256] = {
  85.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  86.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  87.   0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,  /* $ . */
  88.   2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,1,  /* 0-9 ? */
  89.   0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,  /* A-O */
  90.   1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,  /* P-Z _ */
  91.   0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,  /* a-o */
  92.   1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,  /* p-z */
  93.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  94.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  95.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  96.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  97.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  98.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  99.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  100.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  101. };
  102.  
  103. /* table of valid argument characters, 
  104.    0=invalid, 1=valid, 2=valid, but indicates string */
  105. static uint8 valid_argchars[256] = {
  106.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  107.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  108.   0,0,2,0,1,0,0,2,0,0,0,0,0,0,1,0,  /* " $ ' . */
  109.   1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,1,  /* 0-9 ? */
  110.   0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,  /* A-O */
  111.   1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,  /* P-Z _ */
  112.   0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,  /* a-o */
  113.   1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,  /* p-z */
  114.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  115.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  116.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  117.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  118.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  119.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  120.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
  121.   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
  122. };
  123.  
  124. /* valid operators */
  125. #define NUMOPS 10
  126. static char valid_operators[NUMOPS] = {
  127.   '+','-','*','/','%','<','>','&','|','^'
  128. };
  129. #define MAXOPPRI 5
  130. static uint8 op_priority[NUMOPS] = {
  131.   4,4,5,5,5,3,3,2,0,1
  132. };
  133.  
  134.  
  135. char *getsymbol(struct GlobalVars *gv,char *s)
  136. /* read a symbol string into gv->strbuf */
  137. {
  138.   uint8 *vsc = valid_symchars;
  139.   char *b = gv->strbuf;
  140.   int bsize = STRBUFSIZE-2;
  141.  
  142.   if (*s == '@') {  /* '@' is allowed as first character */
  143.     *b++ = *s++;
  144.     bsize--;
  145.   }
  146.   if (vsc[(unsigned char)*s] == 1) {  /* first character valid? */
  147.     *b++ = *s++;
  148.     while (vsc[(unsigned char)*s] && bsize--)
  149.       *b++ = *s++;
  150.   }
  151.   *b = 0;
  152.   return (s);
  153. }
  154.  
  155.  
  156. char *getarg(struct GlobalVars *gv,char *s)
  157. /* read next argument into gv->strbuf */
  158. {
  159.   uint8 v,*vac = valid_argchars;
  160.   char c,*b = gv->strbuf;
  161.   int bsize = STRBUFSIZE-1;
  162.  
  163.   if (*s == '@') {  /* '@' is allowed as first character */
  164.     *b++ = *s++;
  165.     bsize--;
  166.   }
  167.   while ((v = vac[(unsigned char)*s]) && bsize--) {
  168.     *b++ = *s++;
  169.     if (v==2) {  /* string? */
  170.       c = *(s-1);
  171.       for (;;) {
  172.         if (bsize--) {
  173.           if (!(*b++ = *s))  /* string can only be terminated by EOL */
  174.             return (s);
  175.         }
  176.         else
  177.           return (s);
  178.         if (*s++ == c) {
  179.           if (*s==c || *(s-2)=='\\') {
  180.             if (bsize--)  /* "", '' \" or \' don't terminate the string */
  181.               *b++ = *s++;
  182.              else
  183.               return (s);
  184.           }
  185.           else
  186.             break;
  187.         }
  188.       }
  189.     }
  190.   }
  191.   *b = 0;
  192.   return (s);
  193. }
  194.  
  195.  
  196. char *skipspaces(char *s)
  197. /* advance string pointer to the first character, which is no white space */
  198. {
  199.   while (*s==' ' || *s=='\t')
  200.     ++s;
  201.   return (s);
  202. }
  203.  
  204.  
  205. char *remquotes(char *s)
  206. /* remove " or ', if present and return new strbuf-pointer */
  207. {
  208.   int len;
  209.   char c = *s;
  210.  
  211.   if (c=='\"' || c=='\'')  /* string is in quotes */
  212.     if (len = strlen(++s) - 1)
  213.       if (s[len] == c)
  214.         s[len] = 0;
  215.   return (s);
  216. }
  217.  
  218.  
  219. void checkEOL(char *s)
  220. /* check for illegal extra characters on line */
  221. {
  222.   s = skipspaces(s);
  223.   if (*s && *s!='#')  /* only comment is allowed as an extra character */
  224.     error(18);  /* extra characters on line */
  225. }
  226.  
  227.  
  228. char *skipexpression(struct GlobalVars *gv,char *s)
  229. {
  230.   char c;
  231.  
  232.   do {
  233.     s = getarg(gv,s);
  234.     s = skipspaces(s);
  235.     c = *s++;
  236.   }
  237.   while (c!=0 && c!='#' && c!=',');
  238.   return (--s);
  239. }
  240.  
  241.  
  242. void read_macro_params(struct GlobalVars *gv,struct ParsedLine *pl,
  243.                        struct MacroParams *mp,char *op)
  244. /* read parameters and store pointers to their first character */
  245. {
  246.   char c;
  247.  
  248.   mp->param[0] = mp->param0;
  249.   if (pl->branch_hint)
  250.     mp->param0[0] = pl->branch_hint>0 ? '+' : '-';
  251.   for (;;) {
  252.     op = skipspaces(op);
  253.     c = *op;
  254.     if (c!=0 && c!='#') {  /* another parameter? */
  255.       if (mp->narg < (MAX_MACPARAMS-1)) {
  256.         mp->param[++mp->narg] = op;
  257.         op = skipexpression(gv,op);
  258.         c = *op;
  259.         if (c==0 || c=='#') {
  260.           *op = 0;  /* end of line / start of comment */
  261.           return;
  262.         }
  263.         *op++ = 0;  /* next parameter */
  264.       }
  265.       else {
  266.         error(11);  /* too many macro parameters */
  267.         return;
  268.       } 
  269.     }
  270.     else
  271.       return;
  272.   }
  273. }
  274.  
  275.  
  276. char *getexp(struct GlobalVars *gv,char *s,uint32 *val,uint8 s